home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / WASTE 1.2a4 / WASTE Demo / WEDemoFiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-05  |  13.9 KB  |  575 lines  |  [TEXT/CWIE]

  1. /*
  2.     WASTE Demo Project:
  3.     File Handling
  4.         
  5.     Copyright © 1993-1995 Marco Piovanelli
  6.     All Rights Reserved
  7.  
  8.     C port by John C. Daub
  9. */
  10.  
  11.  
  12. #ifndef __WEDEMOAPP__
  13. #include "WEDemoIntf.h"
  14. #endif
  15.  
  16. #ifndef __FOLDERS__
  17. #include <Folders.h>
  18. #endif
  19.  
  20. OSErr    ReadTextFile( const FSSpec *pFileSpec, WEReference we )
  21. {    
  22.     Size            textSize;
  23.     OSErr            err = noErr;
  24.     short            dataForkRefNum = 0;
  25.     short            resForkRefNum = 0;
  26.     Handle            hText = NULL;
  27.     StScrpHandle    hStyles = NULL;
  28.     WESoupHandle    hSoup = NULL;
  29.     
  30.     //    open the data fork with read-only permission
  31.     
  32.     err = FSpOpenDF( pFileSpec, fsRdPerm, &dataForkRefNum );
  33.     if ( err != noErr )
  34.         goto cleanup;
  35.     
  36.     //    get data fork size
  37.     
  38.     err = GetEOF( dataForkRefNum, &textSize );
  39.     if ( err != noErr )
  40.         goto cleanup;
  41.  
  42.     // marco didn't have this, but Michael Kamprath did...i think it's a good thing...
  43.     // set the position in the file from where to start reading
  44.     
  45.     err = SetFPos( dataForkRefNum, fsFromStart, 0L );
  46.     if ( err != noErr )
  47.         goto cleanup;
  48.  
  49.     //    Try to allocate a handle that large, use temporary memory if available
  50.     
  51.     err = NewHandleTemp( textSize, &hText );
  52.     if ( err != noErr )
  53.         goto cleanup;
  54.     
  55.     
  56.     //    read in the text
  57.     
  58.     HLock( hText );
  59.     err = FSRead( dataForkRefNum, &textSize, *hText );
  60.     HUnlock( hText );
  61.     if ( err != noErr )
  62.         goto cleanup;
  63.     
  64.     // again, something Marco didn't have, but Michael did...
  65.     // let's close the data fork before opening up the resource fork.
  66.     
  67.     err = FSClose( dataForkRefNum );
  68.     if ( err != noErr )
  69.         goto cleanup;
  70.     
  71.     //    see if the file has a resource fork
  72.     
  73.     resForkRefNum = FSpOpenResFile( pFileSpec, fsRdPerm );
  74.     if ( resForkRefNum != -1 ) //FSpOpenResFile will return -1 if it fails
  75.     {
  76.         //    look for a style scrap resource (get the first one; the resource ID doesn't matter)
  77.  
  78.         //    this is something I added over Marco's code        
  79.         //    this whole resource stuff is interesting.  first, we could have no resource fork
  80.         //    at all (and that's easy to deal with).  second, we could have a resource fork
  81.         //    and the resources we want ('styl' and 'SOUP').  but third, we could have
  82.         //     a resource fork but not the resources we want.  it's simple to deal with all these
  83.         //    things, but just make sure that you do!
  84.         
  85.         hStyles = (StScrpHandle)Get1IndResource( kTypeStyles, 1 );
  86.         err = ResError();
  87.         if ( (err != noErr) && (err != resNotFound) )
  88.         {
  89.             hStyles = NULL;
  90.             goto CRF;
  91.         }
  92.         else if ( err == resNotFound )
  93.         {
  94.             hStyles = NULL;
  95.         }
  96.         else
  97.             DetachResource( (Handle)hStyles );
  98.             
  99.         //    look for a soup resource as well
  100.         hSoup = (WESoupHandle)Get1IndResource( kTypeSoup, 1 );
  101.         err = ResError();
  102.         if ( (err != noErr) && (err != resNotFound) )
  103.         {
  104.             hSoup = NULL;
  105.             goto CRF;
  106.         }
  107.         else if ( err == resNotFound )
  108.         {
  109.             hSoup = NULL;
  110.         }
  111.         else
  112.             DetachResource( (Handle)hSoup );
  113.  
  114. CRF:        
  115.             CloseResFile( resForkRefNum );
  116.             err = ResError();
  117.             if ( err != noErr )
  118.                 goto cleanup;
  119.                 
  120.     }
  121.     else
  122.     {
  123.         // does not have resource fork, so no style or soup
  124.         
  125.         hStyles = NULL;
  126.         hSoup = NULL;
  127.     }
  128.     
  129.     
  130.     //    insert the text into the WE record
  131.     
  132.     HLock( (Handle)hStyles );
  133.     HLock( (Handle)hSoup );
  134.     HLock( hText );
  135.     err = WEInsert( *hText, textSize, hStyles, hSoup, we );
  136.     HUnlock( hText );
  137.     HUnlock( (Handle)hStyles );
  138.     HUnlock( (Handle)hSoup );
  139.     
  140.     if ( err != noErr )    
  141.         goto cleanup;
  142.     
  143.  
  144.     //    set the insertion point at the beginning of the text
  145.     WESetSelection( 0, 0, we );
  146.     
  147.     //    reset the WE instance modification count
  148.     WEResetModCount( we );
  149.     
  150.     //    clean up and exit
  151.  
  152. cleanup:
  153.  
  154.     // display an alert box if anything went wrong
  155.     if (err != noErr)
  156.     {
  157.         ErrorAlert( err );
  158.     }
  159.  
  160.     ForgetHandle(&hText);
  161.     ForgetHandle((Handle *) &hStyles);
  162.     ForgetHandle((Handle *) &hSoup);
  163.  
  164.     if ( dataForkRefNum > 0 )
  165.     {
  166.         FSClose(dataForkRefNum);
  167.         dataForkRefNum = 0;
  168.     }
  169.     
  170.     if ( resForkRefNum > 0 )
  171.     {
  172.         CloseResFile(resForkRefNum);
  173.         resForkRefNum = 0;
  174.     }
  175.     
  176.     return noErr;
  177. }
  178.  
  179.  
  180. // I added a bunch of other functionality to WriteTextFile(), mostly to show how to use
  181. // temp files, check for locked files, etc. ( all along Apple's recommended way of
  182. // doing things.  - JCD
  183.  
  184. OSErr    WriteTextFile( const FSSpec * pFileSpec, WEReference we )
  185. {
  186.     FInfo            fileInfo;
  187.     Size            textSize;
  188.     Boolean            replacing = false;
  189.     OSErr            err = noErr;
  190.     short            dataForkRefNum = 0;
  191.     short            resForkRefNum = 0;
  192.     Handle            hText = NULL;
  193.     StScrpHandle    hStyles = NULL;
  194.     WESoupHandle    hSoup = NULL;    
  195.     unsigned long    theTime;
  196.     Str255            tempFileName;
  197.     FSSpec            tempFileSpec;
  198.     short            tempVRef;        // volume reference # for the temp file
  199.     long            tempDirID;        // directory ID of the temp file
  200.  
  201.     //    will we be replacing an existing file?
  202.  
  203.     err = FSpGetFInfo( pFileSpec, &fileInfo );
  204.     if ( err == noErr )
  205.         replacing = true;
  206.     else if ( err == fnfErr )
  207.         replacing = false;
  208.     else
  209.     {
  210.         goto cleanup;
  211.     }
  212.  
  213.     // originally, Marco had it so that if the file already existed (replacing == true)
  214.     // then just can the original file and move along.  for the scope of this demo, that
  215.     // really is ok, but generally speaking, not the Apple-recommended way of doing things.
  216.     // since we know we're under (at least) System 7 (due to WASTE's need of it), we know
  217.     // we can use temporary files, so let us do so!
  218.  
  219.     // also, Marco didn't check for locked files (technically, if a file is locked from
  220.     // the Finder, you shouldn't be able to modify it).  let's check for that.
  221.  
  222.     // if the file currently exists (meaning it was saved at some time in the past, be it
  223.     // 5 minutes ago, or 5 days ago), there is a chance that it could be locked (from the
  224.     // Finder's "Get Info" window (or otherwise).  If the file is locked, you cannot
  225.     // save changes.  Therefore, if 'replacing' is true, we have to throw up a message
  226.     // saying that we can't do this, then exit.
  227.     
  228.     if ( replacing )
  229.     {
  230.         err = FSpCheckObjectLock( pFileSpec );
  231.         if ( err != noErr ) // if it returns noErr, the file/directory is NOT locked
  232.         {            
  233.             return err;
  234.         }
  235.     }
  236.     
  237.     if ( replacing )
  238.     {
  239.     
  240.         // create the temporary file name.  the name doesn't have to make sense, just
  241.         // be unique
  242.         
  243.         GetDateTime( &theTime );
  244.         NumToString( theTime, tempFileName );
  245.     
  246.         // find the temporary items folder on the file's volume; create it if necessary
  247.         // it is important that the temp folder (and the temp file) and the "original" target
  248.         // file be on the same volume; if not, FSpExchangeFiles will return diffVolErr (-1303)
  249.         // and won't work
  250.         
  251.         err = FindFolder( pFileSpec->vRefNum, kTemporaryFolderType, kCreateFolder, &tempVRef, &tempDirID );
  252.         if ( err != noErr )
  253.         {
  254.             return err;  // for now, do nothing, just return        
  255.         }
  256.         
  257.         // make an FSSpec for the temp file
  258.         
  259.         err = FSMakeFSSpec( tempVRef, tempDirID, tempFileName, &tempFileSpec );
  260.         if ( (err != noErr) && (err != fnfErr ) )
  261.         {
  262.             return err;
  263.         }
  264.         
  265.     }
  266.  
  267.     //    create a new file.  if we're replacing, make a temp file.  if it's a
  268.     //  new file from the onset, just create the file
  269.     
  270.     // should we allow people to choose the file to create?  i.e. create a TEXT
  271.     // file or a ttro file?  if you'd like to do this, you'll want to find this
  272.     // info out when calling CustomPutFile() and pass that info to this function
  273.     
  274.     if ( replacing )
  275.         FSpCreateResFile( &tempFileSpec, 'trsh', 'trsh', smSystemScript );
  276.     else
  277.         FSpCreateResFile( pFileSpec, kAppSignature, kTypeText, smSystemScript );
  278.     
  279.     err = ResError();
  280.     if ( err != noErr )
  281.     {
  282.         goto cleanup;
  283.     }
  284.     
  285.     //  if replacing an old file, copy the old file information
  286.     if ( replacing )
  287.     {
  288.         err = FSpSetFInfo( &tempFileSpec, &fileInfo );
  289.         if ( err != noErr )
  290.         {
  291.             goto cleanup;
  292.         }
  293.     }
  294.     
  295.         
  296.     //    open the data fork for writing
  297.     if ( replacing )
  298.         err = FSpOpenDF( &tempFileSpec, fsRdWrPerm, &dataForkRefNum );
  299.     else
  300.         err = FSpOpenDF( pFileSpec, fsRdWrPerm, &dataForkRefNum );
  301.         
  302.     if ( err != noErr )
  303.     {
  304.         goto cleanup;
  305.     }
  306.     
  307.     //    set the end-of-file
  308.     
  309.     err = SetEOF( dataForkRefNum, 0 );
  310.     if ( err != noErr )
  311.     {
  312.         goto cleanup;
  313.     }
  314.         
  315.     //    set the position in the file to write from
  316.     
  317.     err = SetFPos( dataForkRefNum, fsFromStart, 0 );
  318.     if ( err != noErr )
  319.     {
  320.         goto cleanup;
  321.     }    
  322.     
  323.     //    get the text handle from the WE instance
  324.     //    WEGetText returns the original handle, not a copy, so don't dispose of it!!
  325.     hText = WEGetText( we );
  326.     textSize = GetHandleSize( hText );
  327.     
  328.     //    write the text
  329.     HLock( hText );
  330.     err = FSWrite( dataForkRefNum, &textSize, *hText );    
  331.     HUnlock( hText );
  332.  
  333.     if ( err != noErr )
  334.     {
  335.         goto cleanup;
  336.     }
  337.     
  338.     //    open the resource file for writing
  339.     
  340.     if ( replacing )
  341.         resForkRefNum = FSpOpenResFile( &tempFileSpec, fsRdWrPerm );
  342.     else
  343.         resForkRefNum = FSpOpenResFile( pFileSpec, fsRdWrPerm );
  344.         
  345.     err = ResError();
  346.     if ( err != noErr )
  347.     {
  348.         goto cleanup;
  349.     }
  350.     
  351.     //    allocate temporary handles to hold the style scrap and the soup
  352.     //    try tapping temporary memory since WECopyRange() could get huge
  353.     
  354.     err = NewHandleTemp( 0, (Handle *) &hStyles );
  355.     if ( err != noErr )
  356.     {
  357.         goto cleanup;
  358.     }
  359.  
  360.     err = NewHandleTemp( 0, (Handle *) &hSoup );
  361.     if ( err != noErr )
  362.     {
  363.         goto cleanup;
  364.     }
  365.  
  366.     //    create the style scrap and the soup
  367.     
  368.  
  369.     err = WECopyRange( 0, LONG_MAX, NULL, hStyles, hSoup, we );
  370.     if ( err != noErr )
  371.     {
  372.         goto cleanup;
  373.     }
  374.  
  375.     
  376.     //    make them resource handles
  377.     
  378.     AddResource( (Handle)hStyles, kTypeStyles, 128, "\p" );
  379.     err = ResError();
  380.     if ( err != noErr )
  381.     {
  382.         goto cleanup;
  383.     }
  384.     
  385.     AddResource( (Handle)hSoup, kTypeSoup, 128, "\p" );
  386.     err = ResError();
  387.     if ( err != noErr )
  388.     {
  389.         goto cleanup;
  390.     }
  391.  
  392.     //    write them to the resource file
  393.     
  394.     ChangedResource( (Handle)hStyles );
  395.     WriteResource( (Handle)hStyles );
  396.     err = ResError();
  397.     if ( err != noErr )
  398.     {
  399.         goto cleanup;
  400.     }
  401.  
  402.     ChangedResource( (Handle)hSoup );
  403.     WriteResource( (Handle)hSoup );
  404.     err = ResError();
  405.     if ( err != noErr )
  406.     {
  407.         goto cleanup;
  408.     }
  409.  
  410.     
  411.  
  412.     //    "clean" this document by resetting the WE instance modification count
  413.     
  414.     WEResetModCount( we );
  415.     
  416.     err = noErr;
  417.     
  418.     //    clean up
  419.  
  420. cleanup:
  421.  
  422.     // display an alert box if anything went wrong
  423.     if (err != noErr)
  424.     {
  425.         ErrorAlert( err );
  426.     }
  427.  
  428.     // remember, don't dispose the hText handle!
  429.     
  430.     ForgetResource( (Handle *) &hStyles );
  431.     ForgetResource( (Handle *) &hSoup );
  432.     
  433.     if ( dataForkRefNum > 0 )
  434.     {    
  435.         FSClose( dataForkRefNum );
  436.         dataForkRefNum = 0;
  437.     }
  438.     
  439.     if ( resForkRefNum > 0 )    
  440.     {
  441.         CloseResFile( resForkRefNum );
  442.         resForkRefNum = 0;
  443.     }
  444.     
  445.     if ( replacing )
  446.     {
  447.         // update the disk with any unwritten data
  448.         
  449.         FlushVol( "\p", tempFileSpec.vRefNum );
  450.  
  451.         // since we were replacing an existing file, let's now swap the original
  452.         // and the temp file.  let's hear it for safe saves.
  453.         
  454.         err = FSpExchangeFiles( &tempFileSpec, pFileSpec );
  455.         if ( err != noErr )
  456.         {
  457.             // handle the error
  458.             
  459.             return err;
  460.         }
  461.         
  462.         // can the temp file since we don't need it anymore
  463.         
  464.         err = FSpDelete( &tempFileSpec );
  465.         if ( err != noErr )
  466.         {
  467.             // handle the error
  468.             
  469.             return err;
  470.         }
  471.     }
  472.     
  473.     // and update the disk with any unwritten data
  474.     
  475.     FlushVol( "\p", pFileSpec->vRefNum );
  476.     
  477.     return err;
  478.     
  479. }
  480.  
  481.  
  482. // this simple routine is meant to give an idea of how the drag translation hook ('xdrg')
  483. // is supposed to work -- in the real world, I should probably handle styled text files,
  484. // PICT files, and maybe other fancier file types here: that is left as an exercise
  485. // for the reader - Marco
  486.     
  487. // well, this exercise for the reader has already been done!  Michael Kamprath has written a
  488. // series of WASTE Object Handlers.  it's a nice code library that suppliments WASTE by giving
  489. // the programmer ready-made stuff for handling PICTs, snd 's, and HFS objects.  Due to the
  490. // fact that this library exists, for Pascal versions of the WASTE Demo App, Marco more or less
  491. // translated Michael's code into Pascal and integrated them into the demo.  Since the demo
  492. // will now be in C, I'm taking the initiative to remove Marco's old drag object handling
  493. // code (this function, and related object handler files, such as WEDemoSounds.p and 
  494. // WEDemoPictures.p) and instead putting in Michael's library.
  495.  
  496. pascal OSErr    TranslateDrag( DragReference theDrag, ItemReference theItem, FlavorType requestedType, Handle dataHandle )
  497. {
  498. #pragma unused ( theDrag, theItem, dataHandle )
  499.  
  500.     OSErr            err = badDragFlavorErr; // assume failure
  501.     
  502.     if ( requestedType != kTypeText )
  503.         return err;
  504.     
  505.     if ( requestedType != kTypeTextReadOnly )
  506.         return err;
  507.  
  508.     err = noErr;
  509.     
  510.     return err;
  511. }
  512.  
  513.  
  514.  
  515.  
  516. /*    The following 2 functions (CheckObjectLock and FSpCheckObjectLock) were taken
  517.     from MoreFiles 1.2.1, a code sample from Apple's DTS.  Here's some info from
  518.     the MoreFiles readme:
  519.     
  520.         A collection of File Manager and related routines
  521.  
  522.         by Jim Luther, Apple Macintosh Developer Technical Support
  523.         with significant code contributions by Nitin Ganatra, Apple Macintosh Developer
  524.         Technical Support
  525.         MoreFile Reference is by Eric Soldan
  526.         Copyright © 1992-1994 Apple Computer, Inc.
  527.         All rights reserved.
  528.     
  529.     Frankly, this is one amazing repository of all sorts of file-related things.  I'd
  530.     check it out if you can. (should be, as of this writing, on ftp.info.apple.com
  531.     in like the /Apple.Support.Services/Developer_Support/ or something like that).
  532.     
  533.     thanx to Alex Rosen for answering my post on comp.sys.mac.programmer.help and pointing
  534.     out MoreFiles to me.
  535.     
  536.     WHAT DO THEY DO?  Oh duh...i should tell you huh?
  537.     
  538.     Both functions do the same thing:  check to see if the object is locked
  539.     (in this case, the object is a file).  This is using in WriteTextFile()
  540.     to prevent overwriting/deleting locked files.
  541.     
  542.     The only difference between these 2 functions are the arguments passed.
  543.     the first takes a vRefNum, dirID and a file name, the second takes an FSSpec
  544.     and then just calls the first based on the FSSpec (just makes for slighly
  545.     neater/readable code)
  546. */
  547.  
  548. pascal    OSErr    CheckObjectLock(short vRefNum, long dirID, StringPtr name)
  549. {
  550.     CInfoPBRec pb;
  551.     OSErr error;
  552.     
  553.     pb.hFileInfo.ioNamePtr = name;
  554.     pb.hFileInfo.ioVRefNum = vRefNum;
  555.     pb.hFileInfo.ioDirID = dirID;
  556.     pb.hFileInfo.ioFDirIndex = 0;    // use ioNamePtr and ioDirID
  557.     error = PBGetCatInfoSync(&pb);
  558.     
  559.     if ( error == noErr )
  560.     {
  561.         // check locked bit
  562.         if ( (pb.hFileInfo.ioFlAttrib & 0x01) != 0 )
  563.             error = fLckdErr;
  564.     }
  565.     return ( error );
  566. }
  567.  
  568. /*****************************************************************************/
  569.  
  570. pascal    OSErr    FSpCheckObjectLock(const FSSpec *spec)
  571. {
  572.     return ( CheckObjectLock(spec->vRefNum, spec->parID, (StringPtr) spec->name) );
  573. }
  574.  
  575.